package cc.magicjson.example.demo.concurrent;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Comparator.comparing;

class DataItem {
    private String timestamp;
    private String data;

    public DataItem(String timestamp, String data) {
        this.timestamp = timestamp;
        this.data = data;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "DataItem{" +
                "timestamp='" + timestamp + '\'' +
                ", data='" + data + '\'' +
                '}';
    }
}

public class MergeDataItemsOp {

    // 示例数据列表1
    private static List<DataItem> list1 = Arrays.asList(
            new DataItem("2023-01-01 10:00", "A"),
            new DataItem("2023-01-01 11:00", "B"),
            new DataItem("2023-01-01 12:00", "C")
    );

    // 示例数据列表2
    private static List<DataItem> list2 = Arrays.asList(
            new DataItem("2023-01-01 10:00", "D"),
            new DataItem("2023-01-01 11:30", "E"),
            new DataItem("2023-01-01 13:00", "F")
    );

    public static void main(String[] args) {
        doMergeListByBiFunction();
    }

    private static void doMergeListByBiFunction() {
        // 按照时间合并两个列表
        List<DataItem> mergedList = mergeAndGroupLists(
                list1,
                list2,
                DataItem::getTimestamp,
                (item1, item2) -> {
                    DataItem result = new DataItem(item1.getTimestamp(), item1.getData());
                    result.setData(result.getData() + "-" + item2.getData());
                    return result;
                }
        );
        System.err.println("================doMergeListByBiFunction================");
        // 输出合并后的列表
        mergedList.forEach(item -> System.err.println(item.toString()));
    }

    public static <T> List<T> mergeAndGroupLists(List<T> sourceList1, List<T> sourceList2,
                                            Function<T, Comparable> keyExtractor,
                                            BiFunction<T, T, T> elementMerger) {
        return mergeAndGroupListsOptimized(sourceList1, sourceList2, keyExtractor, keyExtractor, elementMerger);
    }

    /**
     * 合并两个列表中的元素，根据指定的比较器和分组函数进行分组和合并。
     *
     * @param sourceList1 第一个列表
     * @param sourceList2 第二个列表
     * @param comparableKeyExtractor 比较器函数，用于比较元素的键值
     * @param groupKeyExtractor 分组函数，用于分组元素
     * @param elementMerger 合并函数，用于合并元素
     * @return 合并后的列表
     */
    public static <T> List<T> mergeAndGroupListsOptimized(List<T> sourceList1, List<T> sourceList2, Function<T, Comparable> comparableKeyExtractor,
                                             Function<T, Comparable> groupKeyExtractor,
                                             BiFunction<T, T, T> elementMerger) {
        // 合并两个列表将分并将组结果转换为Map
        Map<Comparable, List<T>> map = (Map<Comparable, List<T>>) Stream.of(sourceList1, sourceList2)
                .flatMap(List::stream)
                // 根据比较器函数进行排序
                .sorted(comparing(comparableKeyExtractor))
                // 根据分组函数进行分组
                .collect(Collectors.groupingByConcurrent(groupKeyExtractor));
        // 合并分组结果
        return map.values().stream()
                // 过滤空列表
                .filter(items -> !items.isEmpty())
                // 合并列表中的元素
                .map(items -> items.stream().reduce(elementMerger::apply).orElse(null))
                // 收集结果
                .collect(Collectors.toList());
    }
}